home *** CD-ROM | disk | FTP | other *** search
- unit Reports;
-
- interface
- Uses SysUtils, Classes,
- ExtCtrls, Chart2FX, Graphics, DB,
- Printers, WinTypes;
-
- Const
- { Note: the first seven styles are exclusive to each other. If more
- than one of these styles is indicated, the first (lowest
- constant) will be chosen }
- ttaLeft = $0000;
- ttaRight = $0001;
- ttaCenter = $0002;
- ttaLeftMargin = $0004;
- ttaRightMargin = $0008;
- ttaBandHCenter = $0010;
- ttaBandVCenter = $0020;
- ttaTopOfBand = $0040;
- ttaBottomOfBand = $0080;
-
- { btXXXX - these styles can be combined to produce a border with
- any combination of lines. For example, btTop + btBottom
- produces a box with only the top and bottom line visible }
- btNone = $0000;
- btBox = $0001;
- btTop = $0002;
- btBottom = $0004;
- btRight = $0008;
- btLeft = $0010;
-
- Type
- { forwards }
- tFixedReportBand = Class;
- tRecurringReportBand = Class;
-
- { enumerated types }
- tReportStatus = ( rsIdle, rsRunning, rsAborted );
- tBandStatus = ( bsContinue, bsDone, bsAbort );
- tShadowStyles = ( stNone, stTopLeft, stTopRight,
- stBottomLeft, stBottomRight );
-
- { Exceptions }
-
- { eReportError is a general sort of exception that gets raised
- whenever you attempt to do something the reporter can't do, like
- calling an output function before the report has begun. }
- eReportError = Class ( Exception );
-
- { eBandOutOfBounds is called when you attempt to print outside the
- margins of the current band. The actual type of the exception
- (eBandOverFlow or eBandUnderFlow) as well as the accompanying
- message lets you know in which the direction you went out of bands.
- This applies to text output only. }
- eBandOutOfBounds = Class ( Exception );
- eBandOverflow = Class ( eBandOutOfBounds );
- eBandUnderflow = Class ( eBandOutOfBounds );
-
-
- { events }
-
- { These events are explained in detail in the declaration of the
- Reporter class below }
- tReportInit = Procedure of Object;
- tReportDone = Procedure of Object;
- tBetweenPages = Procedure of Object;
-
- tBandInit = Procedure ( Band : tRecurringReportBand ) of Object;
-
- tNewBand = Procedure ( Band : tFixedReportBand;
- Var Status : tBandStatus ) of Object;
-
-
- { classes }
-
- { You may read/write the value of a tPrinterUnit variable in one
- of three units: Printer Dots, Inches or Millimeters.
- Reading a value:
- Value := PrinterUnit.AsInches;
-
- Setting a value:
- PrinterUnit.AsDots := 300;
- }
- tPrinterUnit = Class
- Public
- Property AsDots : Integer;
- Property AsInches : Extended;
- Property AsMils : Extended;
- End;
-
- { tConvertPrinterUnit gives you the ability to convert between any
- of the three basic units.
- To Convert Inches to Dots:
- Value := ConvertUnit.Inches(2.0).AsDots;
- To Convert Millimeters to Inches:
- Value := ConvertUnit.Mils(20).AsInches;
- To Convert Dots to Millimeters:
- Value := ConvertUnit.Dots(450).AsMils; }
- tConvertPrinterUnit = Class ( tPrinterUnit )
- Public
- Function Dots ( Value : Integer ) : tPrinterUnit;
- Function Inches ( Value : Extended ) : tPrinterUnit;
- Function Mils ( Value : Extended ) : tPrinterUnit;
- End;
-
-
-
- { I've chosen to implement printing in "BANDS" to facilitate database
- reporting. Each band knows about its own dimensions and can handle
- overflow, etc. without help from the parent reporter. The band needs
- the reporter for access to the canvas.
-
- tFixedReportBand is the basic band object. It provides all report
- output functions (aside from those provided directly through access
- to the reporter's canvas). All band output functions are relative
- to the currently printing band. See the declarations for a
- description of each output call's purpose and parameters }
-
- tFixedReportBand = Class ( tObject )
- Public
- { NextLine advance the print head one "line" based on the height
- of the current font. PreviousLine moves backward one line. }
- Procedure NextLine;
- Procedure PreviousLine;
-
- { TopofBand positions the print head so that the next text output
- call (unless otherwise specified in alignment) will print at the
- top of the band. The other ...OfBand functions behave similarly.
- These functions will not be needed often due to the inclusion of
- ttaLeftMargin, ttaRightMargin, ttaTopOfBand, and ttaBottomOfBand
- styles in the alignment argument of output calls }
- Procedure TopOfBand;
- Procedure LeftOfBand;
- Procedure RightOfBand;
- Procedure BottomOfBand;
-
- { TabTo positions the print head (horizontally) across the page
- with respect to the left margin. Position is specified in
- printer dots. Use Reporter.ConvertWidth if you want to specify
- a tab in units other than dots. RelativeTabTo positions the
- print head with respect to the current position and can be either
- positive or negative }
- Procedure TabTo ( Position : Extended );
- Procedure RelativeTabTo ( Amount : Extended );
- { MoveY and AdjustY behave just like TabTo and RelativeTabTo, except
- they move the print head vertically across the band. }
- Procedure MoveY ( Position : Extended );
- Procedure AdjustY ( Amount : Extended );
-
- { TextOut prints the string specified by Item subject to the
- aligment specified by Alignment. MastRpt provides several
- good examples of the use of Alignment in positioning output }
- Procedure TextOut ( Item : String;
- Alignment : Word );
-
- { BoxTextOut adds the capability of printing lines (with
- optional shadow) around text. BoxStyle (see BoxStyle constants
- above) allows you to place lines around text. BoxOffset specifes
- how far away from the text the box will print. LineWidth specifies
- the width of the sides of the box. ShadowStyle specifies the
- position of the shadow (or no shadow), and ShadowOffset specifies
- the apparent depth of the shadow (distance from the box) }
- Procedure BoxTextOut ( Item : String;
- Alignment : Word;
- BoxStyle : Word;
- BoxOffset : Word;
- LineWidth : Word;
- ShadowStyle : tShadowStyles;
- ShadowOffset : Word );
-
- { DirectMemoOut prints out a pChar vairable in memo format.
- The Width specifies the width of the memo when it prints.
- The height of the memo will be the lesser of:
- 1) the height you specify,
- 2) the height of the band,
- 3) the height needed to display the entire memo.
- Set Height to 0 if you want the memo to use the full band height
- (if it needs to). Any memo output below this point will be
- clipped. The normal alignment constants apply. In addition to
- this, if you specify ttaLeft, ttaRight or ttaCenter, the text
- within the memo box will also be aligned (left,right,center)
- with respect to the memo box's borders. }
- Procedure DirectMemoOut ( MemoText : pChar;
- Height,
- Width : Extended;
- Alignment : Word );
-
-
- { MemoOut works like DirectMemoOut above, except the Memo data is
- pulled directly from a memo field (either tMemo or tDBMemo }
- Procedure MemoOut ( Item : tCustomMemo;
- Height,
- Width : Extended;
- Alignment : Word );
-
-
- { DBMemoOut works like DirectMemoOut above, except the Memo data
- is pulled directly from a table's memo field }
- Procedure DBMemoOut ( Item : tField;
- Height,
- Width : Extended;
- Alignment : Word );
-
- { This routine prints out a tGraphic object.
- Width and Height affect the output as follows:
-
- Width > 0 : Graphic output is exactly Width wide
- Width = 0 : Graphic output is at current Graphic.Width
-
- Height > 0 : Graphic output is exactly Height tall
- Height = 0 : Graphic output is at current Graphic.Height
-
- ScaleWidth and ScaleHeight affect the output as follows:
-
- ScaleWidth = 0 : Graphic output is unchanged.
- ScaleWidth > 0 : Graphic width is multiplied by ScaleWidth/100
-
- ScaleHeight = 0 : Graphic output is unchanged.
- ScaleHeight > 0 : Graphis height is multiplied by ScaleHeight/100
-
- If Width > 0 and ScaleWidth > 0 then ScaleWidth is overridden, and
- likewise for Height and ScaleHeight.
-
- The placement of the graphic may take advantage of all of the
- tTextAligment constants. }
- Procedure PlaceGraphic ( Graphic : tGraphic;
- Alignment : Word;
- Width,
- Height : Extended;
- ScaleWidth,
- ScaleHeight : Word );
-
- { PlaceDBGraphic operates the same way as PlaceGraphic, except
- instead of passing a tGraphic to the procedure, you pass a
- tGraphicField. FishRpt is a good example of how to use this
- procedure. }
- Procedure PlaceDBGraphic ( DBGraphic : tField;
- Alignment : Word;
- Width,
- Height : Extended;
- ScaleWidth,
- ScaleHeight : Word );
-
- { PlaceImage operates the same way as PlaceGraphic, except
- instead of passing a tGraphic to the procedure, you pass a
- tImage. I don't have an example of the use of this function
- in the provided sample reports }
- Procedure PlaceImage ( Image : tImage;
- Alignment : Word;
- Width,
- Height : Extended;
- ScaleWidth,
- ScaleHeight : Word );
-
- { PlaceChartFX operates the same way as PlaceGraphic, except
- instead of passing a tGraphic to the procedure, you pass a
- tChartFX object. The additional option of ColorPrint
- specifies whether or not to attempt to print the chart in
- color (True for color, False for black/white). ChrtRpt is a
- good example of how to use this procedure. }
- Procedure PlaceChartFX ( Chart : tChartFX;
- Alignment : Word;
- Width,
- Height : Extended;
- ScaleWidth,
- ScaleHeight : Word;
- ColorPrint : Boolean );
-
-
- { These four properties are provided for use by those wishing
- to do graphics output directly to the Reporter's canvas. The
- four values bracket the current band's printable area in absolute
- canvas units. Both MastRpt and BoxRpt give examples of how to
- use these properties. }
- Property Left : Word Read fLeft;
- Property Right : Word Read fRight;
- Property Top : Word Read fTop;
- Property Bottom : Word Read fBottom;
- End;
-
-
- { tRecurringReportBand adds support for a band that "fixes" it's
- height to the height needed by the user to print out one
- detail/group band "line". A typical use of the SetBandBegin and
- SetBandEnd procedures is demonstrated in the FishRpt example. }
- tRecurringReportBand = Class ( tFixedReportBand )
- Public
- Procedure SetBandBegin;
- Procedure SetBandEnd;
- Procedure ResetBand;
- End;
-
-
- tReporter = Class ( tPrinter )
- Public
- { This runs the report. The functioning of the report depends
- on declarations of event handlers (see below). }
- Procedure Run;
-
- { these are functions I've inherited from tPrinter that I
- don't want the user to call. So I'm going to redeclare
- them and provide stub procedures }
- Procedure BeginDoc;
- Procedure EndDoc;
- Procedure Abort;
- {+++++++++++++++++}
-
- { The NewPage function calls Reporter's NewPage function, which
- call BetweenPages (user-defined) allowing for margin, header,
- footer, and page orientation changes. Note: this procedure
- will normally _not_ be called to create a new page. It is
- included for the case where the user is not printing
- consecutively down the page, which causes a page break.
- See the BoxRpt demo for an example of NewPage in use. }
- Procedure NewPage;
-
-
- { AddFullPage adds a FullPage band to the report. This will
- seldom be used, and I included it basically to give the
- graphics users easy access to drawing on the full page. This
- procedure _could_ be used to place a watermark on the page. }
- Procedure AddFullPage ( OnNewFullPage : tNewband );
-
- { AddHeader adds a Header band to the report. This will often
- be used in reports. See any of the reports for an example
- of how to use this proceure }
- Procedure AddHeader ( OnNewHeader : tNewBand );
-
- { AddDetail adds a detail band to the report. A Detail band
- consists of two parts: the initialization and the printing.
- In the initialization phase (corresponding to the OnDetailInit
- event), the user can tell the reporter (through the use of
- SetBandBegin...SetBandEnd) how high a complete detail band is.
- This allows the reporter to do two things: 1) prevent the
- detail band from printing across page breaks, and 2) give the
- user the ability to position output calls relative to the
- current position of the band on the page. Without a set band
- height, calls to TopOfBand or BottomOfBand and output calls
- that include the alignment styles ttaTopOfBand, ttaBottomOfBand,
- or ttaBandVCenter will position the print head with relation
- to the top and bottom margins, _not_ with respect to the current
- detail band. See FishRpt and MastRpt (especially FishRpt) for
- an example of setting the band height. }
- Procedure AddDetail ( OnDetailInit : tBandInit;
- OnNewDetail : tNewBand );
-
- { AddGroup adds a group band to the report. A Group band surrounds
- all prior AddDetail and AddGroup bands. See SummRpt for a good
- example of group bands. Using a group band allows you to print
- out detail in groups. Usually, each group and (the only) detail
- correspond to a table, linked to each other in a master-detail
- relationship. The group band's purpose then is to advance the
- master table (and optionally print something) and the detail band's
- purpose is to advance the detail table and print out information.
- OnGroupInit allows you to set the group band's height (see AddDetail).
- OnNewGroup should be used for printing out the group value, and
- initializing report variables. OnGroupSummary should be used to
- advance the table and print out report variables. Again, SummRpt
- is a good example of this process. }
- Procedure AddGroup ( OnGroupInit : tBandInit;
- OnNewGroup : tNewband;
- OnGroupSummary : tNewBand );
-
- { AddFooter adds a footer band to the report. This will usually
- (though not as often as a header band) be used in a report. See
- MastRpt for an example of a footer band. }
- Procedure AddFooter ( OnNewFooter : tNewBand );
-
-
- {Font Routines}
- { SaveFont and RestoreFont work together to preserve a font across
- output calls. These will usually be used in a header or footer
- to prevent changes to the detail band's font across page breaks.
- See any of the reports' header or footer bands for an example
- of these procedures. }
- Procedure SaveFont;
- Procedure RestoreFont;
-
- { CreateFontStyle allows you to save the current font's settings
- by name, to be recalled lated by SetFontStyle. If you want to
- change a Font Style, you need to first use DeleteFontStyle to
- get rid of the current font style, then CreateFontStyle to
- save the new font style. Note that if you don't call
- DeleteFontStyle for any font styles you create, the reporter
- will delete them for you at program termination. See MastRpt for
- an example of the use of named font styles }
- Procedure CreateFontStyle ( StyleName : String );
- Procedure SetFontStyle ( StyleName : String );
- Procedure DeleteFontStyle ( StyleName : String );
-
-
- { returns the current page number }
- Property PageNumber : Word Read fPageNumber;
-
- { returns a list of the currently defined font styles }
- Property FontStyles : tStringList Read fFontStyles;
-
- { returns the reporter's current status. this allows you to
- know if the report terminated normally, or if the user
- aborted the printing }
- Property ReportStatus : tReportStatus Read fReportStatus;
-
- { if you have only a detail band, and you either:
- 1) use a single line in the same font, or
- 2) have set the band's height
- then using the TotalPages property with the total number of
- items to be printed in the report will return the number of
- pages needed to print the report. I do not expect this
- property to be used much, since the complexity of the report
- doesn't really allow (easily) for this kind of calculation }
- Property TotalPages[TotalItems:Word] : Word Read GetTotalPages;
-
- { Use the Orientation property to change the page orientation of
- the report. This property may be used before the report is run,
- or from inside a BetweenPages handler (set through the OnBetweenPages
- property). BoxRpt provides an example of the use of this property
- in the BetweenPages handler. }
- Property Orientation : tPrinterOrientation Read GetOrientation Write SetOrientation;
-
- { These properties set the margins of the page. These properties
- are of type tPrinterUnit, which means that you can read/write
- them using AsDots, AsInches or AsMils, whichever suits your
- fancy. The margins restrict the printable area available to
- the header, footer, and detail/group bands. They also affect
- output calls which include an Alignment specifier. By default,
- these are set to 1 inch apiece. }
- Property TopMargin : tPrinterUnit Read fTopMargin;
- Property BottomMargin : tPrinterUnit Read fBottomMargin;
- Property LeftMargin : tPrinterUnit Read fLeftMargin;
- Property RightMargin : tPrinterUnit Read fRightMargin;
-
- { There are some special cases (most notably memos) where the
- size of a band is not known before the band prints. However,
- you often still want to prevent the band from being split
- across pages. The StretchBand property is for these occasions.
- When you set StretchBand to TRUE, the Reporter calls your band
- Init procedure each time it prints a band. This allows it to
- figure out how tall a band is and prevent page breaks in the
- middle. For an example of this, see the FishRpt demo. }
- Property StretchBand : Boolean Read fStretchBand Write fStretchBand;
-
- { The PreferredUnit property is provided to let you set the
- 'normal' units for the report. After setting PreferredUnit,
- all positioning/output calls that take X, Y, Width, or Height
- arguments will be in terms of the unit you set. Example:
- Reporter.PreferredUnit := puInches;
- Band.TabTo ( 2.0 );
- The above statement causes the print head to move two inches
- from the left margin. }
- Property PreferredUnit : tPreferredUnit Read fPreferredUnit Write fPreferredUnit;
-
- { ConvertWidth and ConvertHeight are provided to give you
- an easy way to convert between units. For example, to
- convert millimeters (width) to dots on the printer:
- ConvertWidth.Mils(20).AsDots
- This is mostly useful in the Place..., TabTo, RelativeTabTo,
- MoveY, and AdjustY procedures. }
- Property ConvertWidth : tConvertPrinterUnit Read fConvertWidth;
- Property ConvertHeight : tConvertPrinterUnit Read fConvertHeight;
-
- { These properties let you specify procedures to run when the
- report is starting, is between pages, and is done respectively.
- OnReportInit is best used to set the margins, open tables, and
- create font styles. OnBetweenPages is best used if you need to swap
- out header/footer bands or change the page orientation in the
- middle of the report (see BoxRpt). OnReportDone is best used
- to close any datasets opened for the report. }
- Property OnReportInit : tReportInit Write fOnReportInit;
- Property OnBetweenPages : tBetweenPages Write fOnBetweenPages;
- Property OnReportDone : tReportDone Write fOnReportDone;
- End;
-
- Var
- { The Reporter itself. Note that there is only one per program }
- Reporter : tReporter;
-
- implementation
- end.
-